#pragma once

#include <memory>
#include <string>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>

namespace cpp_backend
{
    namespace database
    {

        /**
         * @brief 数据库连接接口
         */
        class IConnection
        {
        public:
            virtual ~IConnection() = default;

            /**
             * @brief 检查连接是否有效
             */
            virtual bool IsValid() const = 0;

            /**
             * @brief Ping测试连接
             */
            virtual bool Ping() = 0;

            /**
             * @brief 关闭连接
             */
            virtual void Close() = 0;

            /**
             * @brief 重新连接
             */
            virtual bool Reconnect() = 0;
        };

        /**
         * @brief 连接池基类模板
         *
         * 提供通用的连接池管理功能
         */
        template <typename ConnectionType>
        class ConnectionPool
        {
        public:
            using ConnectionPtr = std::shared_ptr<ConnectionType>;

            /**
             * @brief 构造连接池
             * @param min_size 最小连接数
             * @param max_size 最大连接数
             * @param timeout_ms 获取连接超时时间(毫秒)
             */
            ConnectionPool(size_t min_size = 5, size_t max_size = 20, int timeout_ms = 3000)
                : min_size_(min_size), max_size_(max_size), timeout_ms_(timeout_ms), current_size_(0), is_running_(false) {}

            virtual ~ConnectionPool()
            {
                Shutdown();
            }

            /**
             * @brief 初始化连接池
             */
            virtual bool Initialize()
            {
                std::lock_guard<std::mutex> lock(mutex_);

                if (is_running_)
                {
                    return true;
                }

                // 创建最小数量的连接
                for (size_t i = 0; i < min_size_; ++i)
                {
                    auto conn = CreateConnection();
                    if (conn && conn->IsValid())
                    {
                        idle_connections_.push(conn);
                        ++current_size_;
                    }
                    else
                    {
                        return false;
                    }
                }

                is_running_ = true;
                return true;
            }

            /**
             * @brief 获取连接
             * @return 连接指针，失败返回nullptr
             */
            ConnectionPtr AcquireConnection()
            {
                std::unique_lock<std::mutex> lock(mutex_);

                auto deadline = std::chrono::steady_clock::now() +
                                std::chrono::milliseconds(timeout_ms_);

                while (idle_connections_.empty() && current_size_ >= max_size_)
                {
                    if (cv_.wait_until(lock, deadline) == std::cv_status::timeout)
                    {
                        return nullptr; // 超时
                    }
                }

                ConnectionPtr conn;

                if (!idle_connections_.empty())
                {
                    // 使用空闲连接
                    conn = idle_connections_.front();
                    idle_connections_.pop();

                    // 检查连接有效性
                    if (!conn->IsValid())
                    {
                        if (!conn->Reconnect())
                        {
                            --current_size_;
                            return AcquireConnection(); // 递归重试
                        }
                    }
                }
                else if (current_size_ < max_size_)
                {
                    // 创建新连接
                    conn = CreateConnection();
                    if (conn && conn->IsValid())
                    {
                        ++current_size_;
                    }
                    else
                    {
                        return nullptr;
                    }
                }

                return conn;
            }

            /**
             * @brief 释放连接
             * @param conn 连接指针
             */
            void ReleaseConnection(ConnectionPtr conn)
            {
                if (!conn)
                {
                    return;
                }

                std::lock_guard<std::mutex> lock(mutex_);

                if (conn->IsValid())
                {
                    idle_connections_.push(conn);
                }
                else
                {
                    --current_size_;
                }

                cv_.notify_one();
            }

            /**
             * @brief 关闭连接池
             */
            void Shutdown()
            {
                std::lock_guard<std::mutex> lock(mutex_);

                while (!idle_connections_.empty())
                {
                    auto conn = idle_connections_.front();
                    idle_connections_.pop();
                    conn->Close();
                }

                current_size_ = 0;
                is_running_ = false;
            }

            /**
             * @brief 获取统计信息
             */
            struct Statistics
            {
                size_t idle_count;
                size_t active_count;
                size_t total_count;
                size_t max_size;
            };

            Statistics GetStatistics() const
            {
                std::lock_guard<std::mutex> lock(mutex_);
                return Statistics{
                    idle_connections_.size(),
                    current_size_ - idle_connections_.size(),
                    current_size_,
                    max_size_};
            }

        protected:
            /**
             * @brief 创建新连接（子类实现）
             */
            virtual ConnectionPtr CreateConnection() = 0;

        private:
            size_t min_size_;
            size_t max_size_;
            int timeout_ms_;
            size_t current_size_;
            bool is_running_;

            std::queue<ConnectionPtr> idle_connections_;
            mutable std::mutex mutex_;
            std::condition_variable cv_;
        };

        /**
         * @brief RAII连接管理器
         *
         * 自动管理连接的获取和释放
         */
        template <typename ConnectionType>
        class ConnectionGuard
        {
        public:
            using PoolType = ConnectionPool<ConnectionType>;
            using ConnectionPtr = std::shared_ptr<ConnectionType>;

            ConnectionGuard(PoolType &pool)
                : pool_(pool), conn_(pool.AcquireConnection()) {}

            ~ConnectionGuard()
            {
                if (conn_)
                {
                    pool_.ReleaseConnection(conn_);
                }
            }

            ConnectionPtr Get() const { return conn_; }
            ConnectionPtr operator->() const { return conn_; }
            explicit operator bool() const { return conn_ != nullptr; }

        private:
            PoolType &pool_;
            ConnectionPtr conn_;
        };

    } // namespace database
} // namespace file_server
